package com.agrm.order.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.agrm.api.client.CartClient;
import com.agrm.api.client.GoodClient;
import com.agrm.api.client.MemberClient;
import com.agrm.model.address.pojo.Address;
import com.agrm.model.cart.pojo.CartGoods;
import com.agrm.model.cart.pojo.CartItem;
import com.agrm.model.common.dtos.ResponseResult;
import com.agrm.model.good.pojo.Good;
import com.agrm.model.member.pojo.Member;
import com.agrm.model.order.dto.OrderPay;
import com.agrm.model.order.dto.OrderSubmit;
import com.agrm.model.order.pojo.Order;
import com.agrm.model.order.pojo.OrderItem;
import com.agrm.model.order.search.OrderSearchBean;
import com.agrm.order.mapper.OrderItemMapper;
import com.agrm.order.mapper.OrderMapper;
import com.agrm.order.service.OrderService;
import com.agrm.utils.TimestampGenerator;
import com.agrm.utils.XinUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@CacheConfig(cacheNames = "stmall-order")
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderItemMapper orderItemMapper;

    @Autowired
    private MemberClient memberClient;

    @Autowired
    private CartClient cartClient;

    private static final Snowflake snowflake = IdUtil.getSnowflake();
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private GoodClient goodClient;

    /**
     * 提交订单
     *
     * @param orderSubmit 订单信息
     * @return
     */
    @GlobalTransactional(rollbackFor = Exception.class, propagation = org.apache.seata.tm.api.transaction.Propagation.REQUIRES_NEW)
    @Override
    public int submitOrder(OrderSubmit orderSubmit) {
        String seckillNo = orderSubmit.getSeckillNo();
        if (orderMapper.selectBySeckillNo(seckillNo) != null) {
            return 0;
        }
        CartGoods cartGoods = orderSubmit.getCartGoods();
        Address address = orderSubmit.getAddress();
        if (cartGoods == null || address == null) {
            throw new RuntimeException("购物车或地址不能为空！");
        }

        //对两张表进行操作order 和 order_item
        //1.先保存订单信息到order表中  order_item需要订单主键id
        //1.1 填入订单相关信息
        Order order = new Order();
        if (!XinUtils.isEmpty(orderSubmit.getSeckillNo())) {
            order.setSeckillNo(orderSubmit.getSeckillNo());
        }
        order.setOrderNo(String.valueOf(snowflake.nextId())); //订单编号 雪花算法
        order.setMemberId(orderSubmit.getMemberId()); //会员id
        order.setTotalPay(cartGoods.getPrice());
        order.setPayType("支付宝");
        order.setAlipayTradeNo(TimestampGenerator.generateCustomId()); //支付宝订单号
        order.setStatus(0); //订单状态 未付款
        order.setIsDel(0);


        //1.2 填入收获地址相关信息
        order.setReceiverAddrId(String.valueOf(address.getRegionId())); //收货地址id 行政区县代码
        order.setReceiverName(address.getReceiver()); //收货人
        order.setReceiverPhone(address.getPhone()); //收货人电话
        order.setReceiverAddrDetail(address.getRegionDetail()); //收货详细地址
        order.setOrderComment(orderSubmit.getOrderComment()); //订单备注
        order.setCreatedTime(LocalDateTime.now()); //创建时间

        orderMapper.insert(order); //插入订单信息

        //2.将商品插入到order_item表中
        List<CartItem> goods = cartGoods.getGoods();
        List<Integer> cardIds = new ArrayList<>();
        List<OrderItem> orderItems = new ArrayList<>();
        for (CartItem good : goods) {
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderId(order.getId()); //订单id 需要订单主键id回显
            orderItem.setGoodId(good.getGood().getId()); //商品id
            orderItem.setDealPrice(good.getGood().getPrice()); //成交价格
            orderItem.setCount(good.getQty()); // 数量
            orderItem.setGoodName(good.getGood().getName()); //商品名称
            orderItem.setGoodPic(good.getGood().getPic()); //商品图片
            orderItem.setGoodDesc(good.getGood().getDescription()); //商品描述

            cardIds.add(good.getId());

            orderItems.add(orderItem);
        }
        //3.批量插入
        orderItemMapper.insertBatch(orderItems);
        //4.口库存
        orderSubmit.getCartGoods().getGoods().forEach(it -> {
            goodClient.updateQty(it.getGood().getId(),-(it.getQty()));
        });
        this.rocketMQTemplate.syncSendDelayTimeSeconds("shoplook2025-order-check", order.getId(), 10);
        //5.批量删除
        if (!XinUtils.isEmpty(orderSubmit.getSeckillNo())){
            return 1;
        }
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                //4.从购物车中删除相应的商品
                rocketMQTemplate.asyncSend("stmall-cart-topic", cardIds, new SendCallback() {
                    @Override
                    public void onSuccess(SendResult sendResult) {}
                    @Override
                    public void onException(Throwable throwable) {
                        cartClient.deleteCartByIds(cardIds);
                    }
                });
            }
        });

        return 1;
    }

    @Override
    public boolean saveForSeckill(OrderSubmit orderSubmit) {
        if (orderSubmit.getCartGoods().getGoods().size() != 1) {
            throw new RuntimeException("秒杀商品仅许购置一件！");
        }
        Integer goodId = orderSubmit.getCartGoods().getGoods().get(0).getId();
        Good good = this.goodClient.getSeckillGoodById(goodId).getData();
        if (good == null) {
            throw new RuntimeException("没有该秒杀商品");
        }
        orderSubmit.setSeckillNo(String.valueOf(snowflake.nextId()));
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setResultType(Long.class);
        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("seckill.lua")));
        Member data = this.memberClient.getById(orderSubmit.getMemberId()).getData();
        long result = this.redisTemplate.execute(redisScript, List.of(goodId.toString()), data.getAccount());
        if (result == -100) {
            throw new RuntimeException("您已秒杀过此商品");
        } else if (result == -200) {
            throw new RuntimeException("此商品已结束秒杀");
        } else if (result == -300) {
            throw new RuntimeException("库存已不足");
        }

        this.rocketMQTemplate.asyncSend("stmall-order-topic", orderSubmit, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                redisTemplate.opsForValue().set("stmall-seckill-order:" + data.getAccount() + ":" + goodId, "创建订单消息发送成功");
            }

            @Override
            public void onException(Throwable throwable) {
                redisTemplate.opsForValue().set("stmall-seckill-order:" + data.getAccount() + ":" + goodId, "创建订单消息发送失败");
            }
        });
        return true;
    }

    /**
     * 支付订单
     *
     * @param orderPay
     * @return
     */
    @CacheEvict(cacheNames = "stmall-seckills-member", allEntries = true)
    @Override
    public int payOrder(OrderPay orderPay) {
        //1.查找用户和订单是否合法
        Order order = orderMapper.selectByOrderNo(orderPay.getOrderNo());
        if (order == null) {
            throw new RuntimeException("订单不存在！");
        }
        ResponseResult<Member> memberResponseResult = memberClient.getById(orderPay.getMemberId());
        Member member = memberResponseResult.getData();
        if (member == null) {
            throw new RuntimeException("用户非法！");
        }

        //2.尝试对用户进行扣款
        if (member.getBalance().compareTo(order.getTotalPay()) < 0) {
            throw new RuntimeException("用户余额不足！");
        }
        member.setBalance(member.getBalance().subtract(order.getTotalPay()));
        //2.1更新用户信息
        memberClient.update(member);

        //3.修改订单状态
        order.setPayTime(LocalDateTime.now());
        order.setStatus(1);

        return orderMapper.updateById(order);
    }


    /**
     * 取消订单
     *
     * @param orderNo
     * @return
     */
    @Override
    public int cancelOrder(String orderNo) {
        Order order = orderMapper.selectByOrderNo(orderNo);
        //1.查找订单 判断合法性
        if (order == null) {
            throw new RuntimeException("订单不存在！");
        }

        //2.修改订单状态
        order.setStatus(4);
        order.setUpdatedTime(LocalDateTime.now());

        return orderMapper.updateById(order);
    }


    /**
     * 删除订单
     *
     * @param ids
     * @return
     */
    @Override
    public int deleteByIds(List<Integer> ids) {
        if (ids == null || ids.isEmpty()) {
            throw new RuntimeException("请选择要删除的订单！");
        }

        return orderMapper.logicDeleteByIds(ids);
    }


    @Override
    public Page<Order> findAll(OrderSearchBean osb, Page<Order> page) {
        return orderMapper.findAll(osb, page);
    }

    //不查询订单项
    @Override
    public Order findById(Integer id) {
        return orderMapper.selectById(id);
    }

    //根据订单编号查询唯一订单
    @Override
    public Order findByOrderNo(String orderNo) {
        return orderMapper.selectByOrderNo(orderNo);
    }


//    //保存时，要保存订单项
//    @Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED)
//    @Override
//    public boolean save(Order order) {
//        //生成雪花算法id
//        String snowflakeId = snowflake.nextIdStr();
//        order.setOrderNo(snowflakeId);
//
//        BigDecimal totalPay = BigDecimal.ZERO;
//        if (XinUtils.isNotEmpty(order.getOrderItems())) {//表示保存成功
//            for (OrderItem oi : order.getOrderItems()) {
//                BigDecimal subTotal = oi.getDealPrice().multiply(BigDecimal.valueOf(oi.getCount()));
//                totalPay = totalPay.add(subTotal);
//            }
//        }
//        totalPay = totalPay.setScale(2, RoundingMode.HALF_DOWN);//保留两位小数
//        order.setTotalPay(totalPay);//订单总额
//
//        if (XinUtils.isEmpty(order.getStatus())) {
//            order.setStatus("未支付");
//        }
//        order.setCreatedTime(LocalDateTime.now());//下单时间
//
//        int count = orderMapper.insert(order);
//
//        if (count > 0 && XinUtils.isNotEmpty(order.getOrderItems())) {//表示保存成功
//            Integer orderId = order.getId();//获取自动生成的订单号
//            for (OrderItem oi : order.getOrderItems()) {
//                oi.setId(null);
//                oi.setOrderId(orderId);//设置订单号，进行关联
//                this.orderItemService.save(oi);//保存订单项，扣除库存，需要分布式事务
//            }
//        }
//        //删除购物车项。由于购物车项的删除和订单的创建并不构成紧密关系，所以此处忽略放到同一事务中
//        //也可以放到消息队列中去删除，以提升订单创建性能
//        return count > 0;
//    }

    //修改时，忽略订单项。订单项需单独修改
    @Override
    public boolean update(Order order) {
        return orderMapper.updateById(order) == 1;
    }

    //发货
    @Override
    public boolean updateForShip(Integer orderId) {
        Order order = this.findById(orderId);
        if (order.getStatus().equals(1)) {
            order.setStatus(2);
//            order.setShipTime(LocalDateTime.now());//设置发货时间
            return orderMapper.updateById(order) == 1;
        }
        return false;
    }

    //确认收货
    @Override
    public boolean updateForAccept(Integer orderId) {
        Order order = this.findById(orderId);
        if (order.getStatus().equals(2)) {
            order.setStatus(3);
//            order.setAcceptTime(LocalDateTime.now());
            return orderMapper.updateById(order) == 1;
        }
        return false;
    }

    //批量删除
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED)
    @Override
    public int deleteByIds(List<Integer> ids, boolean logic) {
        if (logic) {//逻辑删除
            int count = 0;

            Order order = new Order();
            order.setIsDel(1);//设置为逻辑删除
            for (Integer id : ids) {
                order.setId(id);
                count += orderMapper.updateById(order);
            }
            return count;
        } else {//物理删除
            //批量删除订单项
            OrderItem oi = new OrderItem();
            for (Integer id : ids) {
                oi.setOrderId(id);
            }
            //删除订单
            return orderMapper.deleteByIds(ids);
        }
    }

}
